#!c:/Python24/python.exe

import cgi, cgitb
cgitb.enable()


#A little hack to ensure that all our functions get the same form data.
StaticFieldStorage = cgi.FieldStorage()
def tmp_func(**not_used):
    return StaticFieldStorage
cgi.FieldStorage = tmp_func



import os
import re
import sys
import keg.config
from string import Template
from cStringIO import StringIO


GET_STR_RE = """(\?[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\),\\\"])?"""

sys.path.append( os.path.join(os.getcwd(), 'keg_modules') )



keg_list_of_url_tuples = []
keg_dict_of_env_vars = {}



def _get_mod(modulePath):
    try:
        aMod = sys.modules[modulePath]
        if not isinstance(aMod, types.ModuleType):
            raise KeyError
    except KeyError:
        # The last [''] is very important!
        aMod = __import__(modulePath, globals(), locals(), [''])
        sys.modules[modulePath] = aMod
    return aMod

def _get_func(fullFuncName):
    """Retrieve a function object from a full dotted-package name."""
    
    # Parse out the path, module, and function
    lastDot = fullFuncName.rfind(u".")
    funcName = fullFuncName[lastDot + 1:]
    modPath = fullFuncName[:lastDot]
    
    aMod = _get_mod(modPath)
    aFunc = getattr(aMod, funcName)
    
    # Assert that the function is a *callable* attribute.
    assert callable(aFunc), u"%s is not callable." % fullFuncName
    
    # Return a reference to the function itself,
    # not the results of the function.
    return aFunc





def preprocessor(args):
    pass


def run_keg(urls_list, env_dict, config):
    template_vars = {}
    html_template = None

    #This line is intended to allow the coder control the headers that
    #are sent. Of course, we default to sending html, but there's no
    #reason that this can't be anything else.
    #
    #Because we do not guarantee the order in which functions are run,
    #care should be taken to ensure that only one function modifies this
    #variable, otherwise the results will be unpredictable.
    template_vars["__headers__"] = "Content-Type: text/html\n\n"

    #This helps all our form remember their input.
    #Note that, you shouldn't remember passwords !!!
    template_vars["content"] = ""
    form = env_dict["cgi"].FieldStorage()

    for key in form.keys():
        template_vars[key] = form[key].value




    preprocessor( (env_dict) )
    
    for url_re, func in urls_list:
        if url_re.search(env_dict["REQUEST_URI"]) != None:
            #Run this function
            output_dict = func( [env_dict] )
            if output_dict == None:
                output_dict = {}
            template_vars.update(output_dict)
##            try:
##                output_dict = func( [env_dict] )
##                template_vars.update(output_dict)
##            except:
##                pass
    
            
    for url_re_str in config.templates.keys():

        url_re_str_tmp = url_re_str
        if url_re_str_tmp[-1] == "$":
            url_re_str_tmp = url_re_str_tmp[:-1]
        url_re_str_tmp = "%s%s$" % (url_re_str_tmp, GET_STR_RE)
        
        if re.compile(url_re_str_tmp).search(env_dict["REQUEST_URI"]) != None:
            #We've found a matching url
            f = open(config.templates[url_re_str], "r")
            html_template = Template(f.read())
            f.close()

            break

    if html_template == None:
        html_template = Template("No matching template found for url: %s." % env_dict["REQUEST_URI"])


    if len(template_vars["__headers__"].lstrip().rstrip()) < 1:
        print "Content-Type: text/html"     # HTML is following
        print                               # blank line, end of headers
    else:
        print template_vars["__headers__"]
        
    print html_template.safe_substitute(template_vars)


            


#importing modules
for module in keg.config.modules:
    mod = _get_mod(module)

    try:
        #We'll try to register any urls the module may be interested in.
        #We expect the module to return a list of url, func tuples
        #The url could be a regex.
        list_of_url_tuples = mod.get_list_of_url_tuples()
        for url_tuple in list_of_url_tuples:
            url_re = url_tuple[0]
            if url_re[-1] == "$":
                url_re = url_re[:-1]
            url_re = "%s%s$" % (url_re, GET_STR_RE)
            keg_list_of_url_tuples.append( (re.compile(url_re), url_tuple[1]) )
    except:
        #Rather crude I admit, but hey . . . it works
        pass



#Setting up environment variables

###A little hack to ensure that all our functions get the same form data.
##StaticFieldStorage = cgi.FieldStorage()
##def tmp_func():
##    return StaticFieldStorage
##cgi.FieldStorage = tmp_func

keg_dict_of_env_vars.update(keg.config.env)
keg_dict_of_env_vars["cgi"] = cgi
for key in os.environ.keys():
    keg_dict_of_env_vars[key] = os.environ[key]
    


run_keg(keg_list_of_url_tuples, keg_dict_of_env_vars, keg.config)

        
